﻿#ifndef _Archive_H__
#define _Archive_H__

#include "kernel/OgreDataStream.h"
#include "kernel/OgreStringVector.h"
#include "kernel/Referenced.h"

namespace FD
{
	namespace Kernel
	{
		class Archive;

		class FD_Kernel_Export FileInfo : public FD::Kernel::CReferenced
		{
		public:
			FileInfo();
			//// The archive in which the file has been found (for info when performing
			//// multi-FD::Kernel::Archive searches, note you should still open through CResourceGroupManager)
			const FD::Kernel::Archive *archive;
			//// The file's fully qualified name
			String filename;
			//// Path name; separated by '/' and ending with '/'
			String path;
			//// Base filename
			String basename;
			//// Compressed size
			size_t compressedSize;
			//// Uncompressed size
			size_t uncompressedSize;
		};

		typedef std::vector<FD::Kernel::FileInfo> FileInfoList;

		class FD_Kernel_Export Archive : public FD::Kernel::CReferenced
		{
		protected:
			//// FD::Kernel::Archive name
			String mName;
			//// FD::Kernel::Archive type code
			String mType;
			//// Read-only flag
			bool mReadOnly;

		public:
			/// <summary> Constructor - don't call direct, used by ArchiveFactory </summary>
			/// <param name = "name"> </param>
			///<param name = "archType"> </param>
			///<returns></returns>
			Archive( const String &name, const String &archType );

			/// <summary> Default destructor.</summary>
			/// <param></param>
			///<returns></returns>
			virtual ~Archive();
			/// <summary> Get the name of this archive </summary>
			/// <param></param>
			/// <returns> String </returns>
			const String &getName() const;
			/// <summary> Returns whether this archive is case sensitive in the way it matches files </summary>
			/// <param></param>
			/// <returns>case sensitive returns true,else return false</returns>
			virtual bool isCaseSensitive() const;
			/// <summary> Loads the archive.
			///  This initializes all the internal data of the class.
			///  Do not call this function directly, it is meant to be used
			///    only by the ArchiveManager class.
			/// </summary>
			/// <param></param>
			/// <returns></returns>
			virtual void load();
			/// <summary> Unloads the archive.
			///warning
			///    Do not call this function directly, it is meant to be used
			///    only by the ArchiveManager class.
			/// </summary>
			/// <param></param>
			/// <returns></returns>
			virtual void unload();
			/// <summary> Reports whether this FD::Kernel::Archive is read-only, or whether the contents
			///	can be updated.
			/// </summary>
			/// <param> </param>
			/// <returns>whether is it read only? read only returns true,else returns false</returns>
			virtual bool isReadOnly() const;
			/// <summary> Open a stream on a given file.
			///note
			///    There is no equivalent 'close' method; the returned stream
			///   controls the lifecycle of this file operation.
			/// </summary>
			///<param> name = "filename" The fully qualified name of the file</param>
			///<param> name = "readOnly" Whether to open the file in read-only mode or not (note,
			///	if the archive is read-only then this cannot be set to false </param>
			/// <returns> A shared pointer to a CDataStream which can be used to
			///    read / write the file. If the file is not present, returns a null
			///	shared pointer.</returns>
			virtual FD::Kernel::DataStreamPtr open(const String &filename, bool readOnly = true) const = 0;
			///<summary> Create a new file (or overwrite one already there).
			///note If the archive is read-only then this method will fail.
			/// </summary>
			/// <param>name= "filename" The fully qualified name of the file </param>
			/// <returns> A shared pointer to a CDataStream which can be used to
			/// read / write the file.</returns>
			virtual FD::Kernel::DataStreamPtr create(const String &filename) const;
			/// <summary> Delete a named file.
			///remarks Not possible on read-only archives
			/// </summary>
			/// <param> name ="filename" The fully qualified name of the file</param>
			/// <returns></returns>
			virtual void remove(const String &filename) const;
			/// <summary> List all file names in the archive.
			///note
			///    This method only returns filenames, you can also retrieve other
			/// </summary>
			///<param> name= "recursive" Whether all paths of the archive are searched (if the
			///    archive has a concept of that</param>
			///<param> name="dirs" Set to true if you want the directories to be listed
			///    instead of files</param>
			/// <returns> A list of filenames matching the criteria, all are fully qualified </returns>
			virtual void list(FD::Kernel::StringVector& result, bool recursive = true, bool dirs = false) = 0;
			///<summary> List all files in the archive with accompanying information.</summary>
			/// <param> name ="recursive" Whether all paths of the archive are searched (if the
			///   archive has a concept of that) </param>
			///<param> name=" dirs" Set to true if you want the directories to be listed
			///    instead of files </param>
			/// <returns> A list of structures detailing quite a lot of information about
			///    all the files in the archive.</returns>
			virtual void listFileInfo(FD::Kernel::FileInfoList& result, bool recursive = true, bool dirs = false ) = 0;
			///<summary> Find all file or directory names matching a given pattern
			///    in this archive.
			///note
			///   This method only returns filenames, you can also retrieve other
			///</summary>
			///<param>name="pattern" The pattern to search for; wildcards (*) are allowed</param>
			///<param>name= "recursive" Whether all paths of the archive are searched (if the
			///    archive has a concept of that)</param>
			///<param> name= "dirs" Set to true if you want the directories to be listed
			///    instead of files </param>
			///<returns> A list of filenames matching the criteria, all are fully qualified</returns>
			virtual void find(FD::Kernel::StringVector& result, const String &pattern, bool recursive = true, bool dirs = false ) = 0;
			/// <summary> Find out if the named file exists (note: fully qualified filename required) </summary>
			/// <param>name = "filename" named file </param>
			/// <returns> exist return true,else return false.</returns>
			virtual bool exists(const String &filename);
			/// <summary> Find all files or directories matching a given pattern in this
			///    archive and get some detailed information about them.
			/// </summary>
			/// <param> name = "pattern" The pattern to search for; wildcards (*) are allowed </param>
			/// <param>name = "recursive" Whether all paths of the archive are searched (if the
			/// archive has a concept of that)</param>
			/// <param> name = "dirs" Set to true if you want the directories to be listed
			///    instead of files </param>
			/// <returns> A list of file information structures for all files matching
			///    the criteria.</returns>
			virtual void findFileInfo(FD::Kernel::FileInfoList& result, const String &pattern, bool recursive = true, bool dirs = false ) const = 0;
			/// <summary> Return the type code of this FD::Kernel::Archive
			/// <param></param>
			/// <returns> type </returns>
			const String &getType() const;

			///public:
			/// <summary> Retrieve the modification time of a given file </summary>
			/// <param> name = "filename" </param>
			/// <returns> time elapsed from modified </returns>
			virtual INT64 getModifiedTime(const String &filename);
		};
	}
}

#endif

